package com.zapi.workflow.service.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zapi.entity.User;
import com.zapi.service.UserService;
import com.zapi.workflow.service.mapper.WfTaskMapper;
import com.zapi.workflow.service.model.dto.CompleteTaskDTO;
import com.zapi.workflow.service.model.dto.ProcessDefinitionDTO;
import com.zapi.workflow.service.model.dto.TaskDisplayDTO;
import com.zapi.workflow.service.model.entity.WfProcessInstance;
import com.zapi.workflow.service.model.entity.WfTask;
import com.zapi.workflow.service.service.WfProcessDefinitionService;
import com.zapi.workflow.service.service.WfProcessInstanceService;
import com.zapi.workflow.service.service.WfTaskService;
import com.zapi.workflow.service.service.WfHistoryActivityService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class WfTaskServiceImpl extends ServiceImpl<WfTaskMapper, WfTask> implements WfTaskService {

    private final WfProcessInstanceService processInstanceService;
    private final WfProcessDefinitionService processDefinitionService;
    private final ObjectMapper objectMapper;
    private final WfHistoryActivityService historyActivityService;
    private final UserService userService;
    
    @Override
    @Transactional
    public void completeTask(CompleteTaskDTO completeTaskDTO) {
        // 1. 获取任务
        WfTask task = baseMapper.selectById(completeTaskDTO.getTaskId());
        if (task == null) {
            throw new RuntimeException("任务不存在: " + completeTaskDTO.getTaskId());
        }
        
        if (task.getStatus() != 1) { // 1-待处理
            throw new RuntimeException("任务状态不正确，无法完成: " + task.getStatus());
        }
        
        // 2. 获取流程实例
        WfProcessInstance instance = processInstanceService.getById(task.getProcessInstanceId());
        if (instance == null) {
            throw new RuntimeException("流程实例不存在: " + task.getProcessInstanceId());
        }
        
        // 3. 获取流程定义
        ProcessDefinitionDTO definitionDTO = processDefinitionService.getDefinitionDTOById(instance.getProcessDefId());
        
        // 4. 更新任务状态
        task.setStatus(completeTaskDTO.isApproved() ? 2 : 3); // 2-已完成 3-已驳回
        task.setCompleteTime(LocalDateTime.now());
        task.setCompleteUser(completeTaskDTO.getOperator());
        task.setComment(completeTaskDTO.getComment());
        baseMapper.updateById(task);
        
        // 4.1 记录任务完成的历史活动
        String comment = completeTaskDTO.isApproved() ? 
            "审批通过：" + completeTaskDTO.getComment() : 
            "审批驳回：" + completeTaskDTO.getComment();
            
        historyActivityService.recordActivityEnd(
            task.getProcessInstanceId(),
            task.getNodeId(),
            completeTaskDTO.getOperator(),
            comment
        );
        
        // 5. 如果是驳回，结束流程或退回（这里简化处理为结束流程）
        if (!completeTaskDTO.isApproved()) {
            instance.setStatus(2); // 已结束
            instance.setEndTime(LocalDateTime.now());
            processInstanceService.updateById(instance);
            return;
        }
        
        // 6. 更新流程变量
        updateProcessVariables(instance, completeTaskDTO.getVariables());
        
        // 7. 找到当前节点的流出连线
        List<com.zapi.workflow.service.model.dto.FlowDTO> outgoingFlows = definitionDTO.getFlows().stream()
                .filter(flow -> task.getNodeId().equals(flow.getFrom()))
                .collect(Collectors.toList());
        
        if (outgoingFlows.isEmpty()) {
            // 没有流出连线，流程结束
            instance.setStatus(2); // 已结束
            instance.setEndTime(LocalDateTime.now());
            processInstanceService.updateById(instance);
            return;
        }
        
        // 8. 获取下一个节点ID（审批节点通常只有一条流出连线）
        String nextNodeId = outgoingFlows.get(0).getTo();
        
        // 9. 更新流程实例当前节点
        instance.setCurrentNodeId(nextNodeId);
        processInstanceService.updateById(instance);
        
        // 10. 处理下一个节点
        WfProcessInstanceServiceImpl instanceService = (WfProcessInstanceServiceImpl) processInstanceService;
        instanceService.processNextNode(instance, definitionDTO, nextNodeId);
    }
    
    @Override
    public IPage<WfTask> getUserTasks(Page<WfTask> page, String assignee) {
        return baseMapper.selectUserTasks(page, assignee, 1); // 查询代办任务
    }
    
    /**
     * 更新流程变量
     */
    private void updateProcessVariables(WfProcessInstance instance, Map<String, Object> newVariables) {
        if (newVariables == null || newVariables.isEmpty()) {
            return;
        }
        
        try {
             // 1. 解析现有变量
             Map<String, Object> variables = null;
             if (instance.getVariables() != null) {
                 @SuppressWarnings("unchecked")
                 Map<String, Object> parsedVariables = objectMapper.readValue(instance.getVariables(), Map.class);
                 variables = parsedVariables;
             }
            
            // 2. 合并新变量
            if (variables == null) {
                variables = newVariables;
            } else {
                variables.putAll(newVariables);
            }
            
            // 3. 保存更新后的变量
            instance.setVariables(objectMapper.writeValueAsString(variables));
            processInstanceService.updateById(instance);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("更新流程变量失败", e);
        }
    }
    
    @Override
    public IPage<TaskDisplayDTO> getUserTasksWithDisplayInfo(Page<TaskDisplayDTO> page, String assignee) {
        // 1. 先查询基础任务信息
        Page<WfTask> taskPage = new Page<>(page.getCurrent(), page.getSize());
        IPage<WfTask> taskResult = getUserTasks(taskPage, assignee);
        
        // 2. 转换为显示DTO并填充关联信息
        List<TaskDisplayDTO> displayList = taskResult.getRecords().stream()
                .map(this::convertToTaskDisplayDTO)
                .collect(Collectors.toList());
        
        // 3. 构建分页结果
        Page<TaskDisplayDTO> resultPage = new Page<>(page.getCurrent(), page.getSize(), taskResult.getTotal());
        resultPage.setRecords(displayList);
        
        return resultPage;
    }
    
    /**
     * 转换任务为显示DTO
     */
    private TaskDisplayDTO convertToTaskDisplayDTO(WfTask task) {
        TaskDisplayDTO dto = new TaskDisplayDTO();
        
        // 基础任务信息
        dto.setId(task.getId());
        dto.setProcessInstanceId(task.getProcessInstanceId());
        dto.setNodeId(task.getNodeId());
        dto.setNodeName(task.getNodeName());
        dto.setAssignee(task.getAssignee());
        dto.setStatus(task.getStatus());
        dto.setPriority(task.getPriority());
        dto.setCreateTime(task.getCreateTime());
        dto.setCompleteTime(task.getCompleteTime());
        dto.setVariables(task.getVariables());
        
        try {
            // 获取流程实例信息
            WfProcessInstance instance = processInstanceService.getById(task.getProcessInstanceId());
            if (instance != null) {
                dto.setProcessDefId(instance.getProcessDefId());
                dto.setProcessKey(instance.getProcessKey());
                dto.setBusinessKey(instance.getBusinessKey());
                dto.setStartUser(instance.getStartUser());
                dto.setProcessStartTime(instance.getStartTime());
                
                // 获取流程定义信息
                ProcessDefinitionDTO definition = processDefinitionService.getDefinitionDTOById(instance.getProcessDefId());
                if (definition != null) {
                    // 任务名称：使用流程定义的名称
                    dto.setTaskName(definition.getName());
                    
                    // 表单名称：根据业务类型判断
                    dto.setBusinessType(definition.getBusinessType());
                    dto.setSystemFormKey(definition.getSystemFormKey());
                    dto.setBusinessFormId(definition.getBusinessFormId());
                    
                    if (definition.getBusinessType() == 1) {
                        // 系统表单
                        String formName = definition.getSystemFormKey() != null ? 
                            "系统表单(" + definition.getSystemFormKey() + ")" : "系统表单(未配置)";
                        dto.setFormName(formName);
                    } else if (definition.getBusinessType() == 2) {
                        // 自定义表单
                        String formName = definition.getBusinessFormId() != null ? 
                            "自定义表单(" + definition.getBusinessFormId() + ")" : "自定义表单(未配置)";
                        dto.setFormName(formName);
                    } else {
                        dto.setFormName("未配置表单");
                    }
                } else {
                    // 流程定义不存在时的默认值
                    dto.setTaskName(instance.getProcessKey());
                    dto.setFormName("未配置表单");
                }
                
                // 获取发起人真实姓名
                dto.setStartUserName(getUserRealName(instance.getStartUser()));
                
                // 获取审批人真实姓名
                dto.setAssigneeName(getUserRealName(task.getAssignee()));
                
            } else {
                // 流程实例不存在时的默认值
                dto.setTaskName("未知任务");
                dto.setFormName("加载失败");
                dto.setStartUserName("未知");
                dto.setAssigneeName("未知");
            }
            
        } catch (Exception e) {
            // 异常时使用默认值
            dto.setTaskName("未知任务");
            dto.setFormName("加载失败");
            dto.setStartUserName("未知");
            dto.setAssigneeName(getUserRealName(task.getAssignee()));
        }
        
        return dto;
    }
    
    /**
     * 根据用户ID获取真实姓名
     */
    private String getUserRealName(String userId) {
        if (userId == null || userId.trim().isEmpty()) {
            return "未知用户";
        }
        
        try {
            // 尝试将userId转换为Long类型
            Long userIdLong = Long.parseLong(userId);
            User user = userService.getById(userIdLong);
            if (user != null && user.getRealName() != null && !user.getRealName().trim().isEmpty()) {
                return user.getRealName();
            }
        } catch (NumberFormatException e) {
            // 如果userId不是数字，尝试通过用户名查询
            User user = userService.findByUsername(userId);
            if (user != null && user.getRealName() != null && !user.getRealName().trim().isEmpty()) {
                return user.getRealName();
            }
        } catch (Exception e) {
            // 查询失败，返回用户ID
        }
        
        // 如果查询失败或没有真实姓名，返回用户ID
        return userId;
    }
}
    